package leetcode_day._2021._202111;

/**
 * @author yzh
 * @version 1.0
 * @date 2021/11/23 13:36
 * 亲密字符串
 * 给你两个字符串 s 和 goal ，只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果，就返回 true ；否则返回 false 。
 * 交换字母的定义是：取两个下标 i 和 j （下标从 0 开始）且满足 i != j ，接着交换 s[i] 和 s[j] 处的字符。
 * 例如，在 "abcd" 中交换下标 0 和下标 2 的元素可以生成 "cbad" 。
 * 算法：字符串 + 模拟
 * 只能交换一次
 * s 与 goal 的长度或词频不同时，直接返回 false
 * s 与 goal 不同的字符数量为 2 或者不同的数量为 0，但 s 的字符串数量要 >= 2, 返回 true
 * 注意：aa 和 aa 是亲密字符串
 */
public class _23_859 {
    public static void main(String[] args) {
        System.out.println(new _23_859().buddyStrings("ab", "ab"));
    }

    public boolean buddyStrings(String s, String goal) {
        int n = s.length(), m = goal.length();
        if (n != m) return false;
        int[] a = new int[26], b = new int[26];
        // s 和 goal 不相同字符的数量
        int sum = 0;
        // 统计词频和不相同字符的数量
        for (int i = 0; i < n; i++) {
            int x = s.charAt(i) - 'a', y = goal.charAt(i) - 'a';
            ++a[x]; ++b[y];
            if (x != y) ++sum;
        }
        boolean flag = false;
        for (int i = 0; i < 26; i++) {
            // 词频不同
            if (a[i] != b[i]) return false;
            // ab 与 ab 不是
            if (a[i] > 1) flag = true;
        }
        return sum == 2 || (sum == 0 && flag);
    }

}
